package com.xiyuan.smartutils;

import com.xiyuan.smartutils.constants.EnumConstants;

import java.text.DecimalFormat;

/**
 * 金额相关工具类
 *
 * @version v1.0.0 @author lgz 2017-8-27 新建与整理
 */

public final class Amounts implements EnumConstants {
    
    private static final String NEGATIVE = "-";
    
    
    /**
     * 分格式化策略
     */
    public enum FenType {
        /**
         * 四舍五入
         */
        CEIL,
        /**
         * 向上取整
         */
        ROUND,
        /**
         * 向下取整
         */
        FLOOR
    }
    
    /**************************************************************/
    /****************************分转元 ***************************/
    /**************************************************************/
    
    /**
     * 金额分，转为字符串元，转化后是2位小数点
     *
     * @param fen 金额分值，能转化成长整型的字符串
     * @return 金额元值字符串
     */
    public static String toYuan(String fen) {
        Asserts.isInteger(fen);
        return toYuan(Long.parseLong(fen));
    }
    
    
    /**
     * 金额分，转为字符串元，转化后最大2位小数点，没有的不保留小数点
     *
     * @param fen 金额分值
     * @return 金额元值字符串
     */
    public static String toYuan(long fen) {
        return fen == 0 ? "0" : Double.valueOf(new DecimalFormat("#.##").format(fen / 100.0)).toString();
    }
    
    /**
     * 金额分，转为字符串元，转化后强制为2位小数点，没有的为.00
     *
     * @param fen 金额分值
     * @return 金额元值字符串
     */
    public static String toYuanRadix(String fen) {
        Asserts.isInteger(fen);
        return toYuanRadix(Long.parseLong(fen));
    }
    
    /**
     * 金额分，转为字符串元，转化后强制为2位小数点，没有的为.00
     *
     * @param fen 金额分值
     * @return 金额元值字符串，如"2.00"
     */
    public static String toYuanRadix(long fen) {
        final int ten = 10;
        double result = (double) fen / 100;
        long radix = fen % 100;
        StringBuilder ret = new StringBuilder(new DecimalFormat("#.##").format(result));
        if (radix == 0) {
            ret.append(".00");
        }
        else if (radix == ten) {
            ret.append(0);
        }
        return ret.toString();
    }
    
    
    /**************************************************************/
    /******************************元转分 **************************/
    /**************************************************************/
    
    /**
     * 金额元，转为字符串分，转化后是2位小数点
     *
     * @param yuan         金额元值字符串
     * @param defaultValue 默认值
     * @param type         Type
     * @param allowError   是否允许错误
     * @return 金额分值字符串
     */
    private static long toFen(String yuan, long defaultValue, FenType type, boolean allowError) {
        
        if (!Validates.isFloat(yuan)) {
            Asserts.as(allowError ? null : "金额格式无效：%s", yuan);
            return defaultValue;
        }
        if (type == null) {type = FenType.FLOOR;}
        
        boolean isNegative = false;
        if (yuan.indexOf(NEGATIVE) != -1) {
            isNegative = true;
            yuan = yuan.substring(1);
        }
        
        int index = yuan.indexOf('.');
        long value = index == 0 ? 0 : Long.parseLong(index == -1 ? yuan : yuan.substring(0, index)) * 100;
        if (index != -1 && index != yuan.length() - 1) {
            String rad = yuan.substring(index + 1);
            int len = rad.length();
            op:
            for (int i = 0, l = 10, d = l; i < len; i++, l /= d) {
                int v = (rad.charAt(i) - '0'), vv = v * l;
                if (l > 0) {
                    value += vv;
                    continue;
                }
                switch (type) {
                    case CEIL:
                        // 四舍五入
                        if (v > 4) {value++;}
                        break op;
                    case ROUND:
                        // 向上取整
                        if (v > 0) {value++;}
                        break op;
                    default:
                        break op;
                }
            }
            
        }
        return (isNegative) ? -value : value;
    }
    
    /**
     * 金额字符串转long型金额分，number数字格式不正确，则返回默认值
     * <p>
     * type 说明：<br/>
     * FenType.CEIL:四舍五入,例：<br/>
     * &nbsp;&nbsp;100.003 -> 10000<br/>
     * &nbsp;&nbsp;100.004 -> 10000<br/>
     * &nbsp;&nbsp;100.005 -> 10001<br/>
     * &nbsp;&nbsp;100.006 -> 10001<br/>
     * FenType.FLOOR 向下取整，例：<br/>
     * &nbsp;&nbsp;100.003 -> 10000<br/>
     * &nbsp;&nbsp;100.004 -> 10000<br/>
     * &nbsp;&nbsp;100.005 -> 10000<br/>
     * &nbsp;&nbsp;100.006 -> 10000<br/>
     * FenType.ROUND 向上取整，例：<br/>
     * &nbsp;&nbsp;100.001 -> 10001<br/>
     * &nbsp;&nbsp;100.004 -> 10001<br/>
     * &nbsp;&nbsp;100.005 -> 10001<br/>
     * &nbsp;&nbsp;100.006 -> 10001<br/>
     * </p>
     *
     * @param number       金额
     * @param defaultValue 默认值
     * @param type         类型
     * @return 分
     */
    public static long toFen(String number, long defaultValue, FenType type) {
        return toFen(number, defaultValue, type, true);
    }
    
    /**
     * 金额字符串转long型金额分
     * <p>
     * type 说明：<br/>
     * FenType.CEIL:四舍五入,例：<br/>
     * &nbsp;&nbsp;100.003 -> 10000<br/>
     * &nbsp;&nbsp;100.004 -> 10000<br/>
     * &nbsp;&nbsp;100.005 -> 10001<br/>
     * &nbsp;&nbsp;100.006 -> 10001<br/>
     * FenType.FLOOR 向下取整，例：<br/>
     * &nbsp;&nbsp;100.003 -> 10000<br/>
     * &nbsp;&nbsp;100.004 -> 10000<br/>
     * &nbsp;&nbsp;100.005 -> 10000<br/>
     * &nbsp;&nbsp;100.006 -> 10000<br/>
     * FenType.ROUND 向上取整，例：<br/>
     * &nbsp;&nbsp;100.001 -> 10001<br/>
     * &nbsp;&nbsp;100.004 -> 10001<br/>
     * &nbsp;&nbsp;100.005 -> 10001<br/>
     * &nbsp;&nbsp;100.006 -> 10001<br/>
     * </p>
     *
     * @param number 金额
     * @param type   类型
     * @return 分
     */
    public static long toFen(String number, FenType type) {
        return toFen(number, 0, type, false);
    }
    
    /**
     * 金额字符串转long型金额分，number数字格式不正确，则返回默认值
     * 例：<br/>
     * &nbsp;&nbsp;100.003 -> 10000<br/>
     * &nbsp;&nbsp;100.004 -> 10000<br/>
     * &nbsp;&nbsp;100.005 -> 10000<br/>
     * &nbsp;&nbsp;100.006 -> 10000<br/>
     * &nbsp;&nbsp;100.01  -> 10000<br/>
     * &nbsp;&nbsp;100.1   -> 10010<br/>
     * &nbsp;&nbsp;100.10  -> 10010<br/>
     * &nbsp;&nbsp;100.15  -> 10015<br/>
     *
     * @param number       金额
     * @param defaultValue 默认值
     * @return 分
     */
    public static long toFen(String number, long defaultValue) {
        return toFen(number, defaultValue, FenType.FLOOR, true);
    }
    
    /**
     * 金额字符串转long型金额分
     * 例：<br/>
     * &nbsp;&nbsp;100.003 -> 10000<br/>
     * &nbsp;&nbsp;100.004 -> 10000<br/>
     * &nbsp;&nbsp;100.005 -> 10000<br/>
     * &nbsp;&nbsp;100.006 -> 10000<br/>
     * &nbsp;&nbsp;100.01  -> 10000<br/>
     * &nbsp;&nbsp;100.1   -> 10010<br/>
     * &nbsp;&nbsp;100.10  -> 10010<br/>
     * &nbsp;&nbsp;100.15  -> 10015<br/>
     *
     * @param number 金额
     * @return 分
     */
    public static long toFen(String number) {
        return toFen(number, FenType.FLOOR);
    }
    
    
    /**
     * 金额字符串转int型金额分，number数字格式不正确，则返回默认值
     * <p>
     * type 说明：<br/>
     * FenType.CEIL:四舍五入,例：<br/>
     * &nbsp;&nbsp;100.003 -> 10000<br/>
     * &nbsp;&nbsp;100.004 -> 10000<br/>
     * &nbsp;&nbsp;100.005 -> 10001<br/>
     * &nbsp;&nbsp;100.006 -> 10001<br/>
     * FenType.FLOOR 向下取整，例：<br/>
     * &nbsp;&nbsp;100.003 -> 10000<br/>
     * &nbsp;&nbsp;100.004 -> 10000<br/>
     * &nbsp;&nbsp;100.005 -> 10000<br/>
     * &nbsp;&nbsp;100.006 -> 10000<br/>
     * FenType.ROUND 向上取整，例：<br/>
     * &nbsp;&nbsp;100.001 -> 10001<br/>
     * &nbsp;&nbsp;100.004 -> 10001<br/>
     * &nbsp;&nbsp;100.005 -> 10001<br/>
     * &nbsp;&nbsp;100.006 -> 10001<br/>
     * </p>
     *
     * @param number       金额
     * @param defaultValue 默认值
     * @param type         类型
     * @return 分
     */
    public static int toFen(String number, int defaultValue, FenType type) {
        return (int) toFen(number, defaultValue, type, true);
    }
    
    public static long toFen(double yuan) {
        return toFen(String.valueOf(yuan));
    }
    
    public static long toFen(double yuan, FenType type) {
        return toFen(String.valueOf(yuan), type);
    }
    
    /**
     * 金额字符串转int型金额分，number数字格式不正确，则返回默认值
     * 例：<br/>
     * &nbsp;&nbsp;100.003 -> 10000<br/>
     * &nbsp;&nbsp;100.004 -> 10000<br/>
     * &nbsp;&nbsp;100.005 -> 10000<br/>
     * &nbsp;&nbsp;100.006 -> 10000<br/>
     * &nbsp;&nbsp;100.01  -> 10000<br/>
     * &nbsp;&nbsp;100.1   -> 10010<br/>
     * &nbsp;&nbsp;100.10  -> 10010<br/>
     * &nbsp;&nbsp;100.15  -> 10015<br/>
     *
     * @param number       金额
     * @param defaultValue 默认值
     * @return 分
     */
    public static int toFen(String number, int defaultValue) {
        return toFen(number, defaultValue, FenType.FLOOR);
    }
    
    
    /**************************************************************/
    /******************************转折口 **************************/
    /**************************************************************/
    /**
     * 通过原价和促销价，求折扣
     *
     * @param price    原价
     * @param priceNew 促销价
     * @return 返回减钱折扣值，如9.92折,10折
     */
    public static String toDiscount(String price, String priceNew) {
        long priceLong = toFen(price, FenType.FLOOR);
        long priceNewLong = toFen(priceNew, FenType.FLOOR);
        return toDiscount(priceLong, priceNewLong);
    }
    
    /**
     * 通过原价和促销价，求折扣
     *
     * @param price    原价
     * @param priceNew 促销价
     * @return 返回减钱折扣值，如9.92折,10折
     */
    public static String toDiscount(long price, long priceNew) {
        long priceSave = price - priceNew;
        if (priceSave == 0) {return "10";}
        else {return toYuan(priceNew * 1000 / price);}
    }
    
    
    public static String toChinese(Long fen) {
        return Numbers.toChinese(fen, 2, false);
    }
}
